<script>
function doLog(msg)
{
    var d = document.createElement("div");
    d.innerHTML = msg;
    document.body.appendChild(d);
}

function report(msg, res)
{
    if (res)
        msg = "<font color=green>PASS:</font>" + msg;
    else
        msg = "<font color=red>FAIL:</font>" + msg;
    doLog(msg);
}

/*
 Tree:
    a
        b
            c
        d
            e
        f
        g
            h
   b, c are rejected,
   d is skipped.
   g is rejected
*/
function kid(parent) {
    var newKid = document.createElement("div");
    parent.appendChild(newKid);
    return newKid;
}

function test() {
    if (window.testRunner)
        testRunner.dumpAsText();

    var wrapper = document.createElement("div"); // just to have one more level up.

    var a = kid(wrapper);
        var b = kid(a);
            var c = kid(b);
        var d = kid(a);
            var e = kid(d);
        var f = kid(a);
        var g = kid(a);
            var h = kid(g);
    a.setAttribute("id", "a");
    b.setAttribute("id", "b");
    c.setAttribute("id", "c");
    d.setAttribute("id", "d");
    e.setAttribute("id", "e");
    f.setAttribute("id", "f");
    g.setAttribute("id", "g");
    h.setAttribute("id", "h");

    function filter(node) {
        if (node == b || node == c || node == g)
            return NodeFilter.FILTER_REJECT;
        if (node == d)
            return NodeFilter.FILTER_SKIP;
        return NodeFilter.FILTER_ACCEPT;
    }
    
    var tw = document.createTreeWalker(a, NodeFilter.SHOW_ALL, filter, true);
    report("Proper a.firstChild()", tw.firstChild() == e);

    tw.currentNode = b;
    report("Proper b.firstChild()", tw.firstChild() == null);
    // shouldn't move.
    report("Shouldn't move", tw.currentNode == b);

    tw.currentNode = b;
    report("Proper b.nextSibling()", tw.nextSibling() == e);

    // This is because we should treat 'b' as skipped when we are under it.
    tw.currentNode = c;
    report("Proper c.nextSibling()", tw.nextSibling() == e);

    tw.currentNode = e;
    report("Proper e.nextSibling()", tw.nextSibling() == f);

    tw.currentNode = f;
    report("Proper f.previousSibling()", tw.previousSibling() == e);
    tw.currentNode = e;
    report("Proper e.previousSibling()", tw.previousSibling() == null);
    report("Shouldn't move", tw.currentNode == e);

    tw.currentNode = h;
    report("Proper h.previousSibling()", tw.previousSibling() == f);

    tw.currentNode = g;
    report("Proper g.previousSibling()", tw.previousSibling() == f);
    // f is g's previous sibling, but not the other way around :-)
    tw.currentNode = f;
    report("Proper f.nextSibling()", tw.nextSibling() == null);
    report("Proper f.parentNode()", tw.parentNode() == a);
    report("Proper a.parentNode()", tw.parentNode() == null);

    // Test exit/capture.
    tw.currentNode = a.parentNode;
    report("Proper a's parent.nextNode()", tw.nextNode() == a);
    // Should get caught..
    report("Re-capture #1", tw.previousNode() == null);
    report("Re-capture #2", tw.parentNode() == null);
    report("nextNode from a", tw.nextNode() == e);
    report("prevNode to a", tw.previousNode() == a);

    doLog("All done!");
}

</script>
<body onload="test()">
